﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DAL.Helpers;
using Model.Entities;
using Model.RepositoryInterfaces;
using Model.ViewModels;
using NHibernate;

namespace DAL.Repositories
{
    public class RoomRepository:IRoomRepository
    {
        #region Implementation of IRoomRepository

        public void Create(int apartmentId, Room room)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    try
                    {
                        var apartment = session.Get<Apartment>(apartmentId);
                        apartment.Rooms.Add(room);
                        session.Update(apartment);
                        transaction.Commit();
                    }
                    catch (ADOException exception)
                    {
                        throw new Exception(exception.Message);
                    }
                }
            }
        }

        public Room Read(int roomId)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                var room = session.Get<Room>(roomId);
                return room;
            }
        }

        public IList<RoomVm> ReadAll(int apartmentId)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                var apartment = session.Get<Apartment>(apartmentId);

                return apartment.Rooms.Select(room => new RoomVm()
                {
                    Id = room.Id, 
                    Group = room.RoomGroup, 
                    Mark = room.Mark, 
                    Type = EnumHelper.GetEnumName(typeof (TypeOfRoom), room.Type), 
                    Name = room.Name, Area = room.AreaValue
                }).ToList();
            }
        }

        public void Update(int apartmentId, RoomCrudAdminVm viewModel)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    try
                    {
                        var apartment = session.Get<Apartment>(apartmentId);

                        foreach (var room in apartment.Rooms)
                        {
                            if (room.Id == viewModel.Id)
                            {
                                room.RoomGroup = (int)viewModel.RoomGroup;
                                room.Mark = viewModel.Mark;
                                room.Type = viewModel.Type;
                                room.Name = viewModel.Name;
                                room.AreaValue = (double)viewModel.Area;
                                break;
                            }
                        }

                        session.Update(apartment);
                        transaction.Commit();
                    }
                    catch (ADOException exception)
                    {
                        throw new Exception(exception.Message);
                    }
                }
            }
        }

        public void Delete(int apartmentId, int roomId)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    try
                    {
                        var apartment = session.Get<Apartment>(apartmentId);

                        for (var i = 0; i < apartment.Rooms.Count; i++)
                        {
                            if (apartment.Rooms[i].Id == roomId)
                            {
                                apartment.Rooms.RemoveAt(i);
                                break;
                            }
                        }

                        session.Update(apartment);
                        transaction.Commit();
                    }
                    catch (ADOException exception)
                    {
                        throw new Exception(exception.Message);
                    }
                }
            }
        }

        public void GenerateRoomsByModel(int apartmentId)
        {
            using (var session = NHibernateHelper.OpenSession())
            {
                using (var transaction = session.BeginTransaction())
                {
                    try
                    {
                        var mainApartment = session.Get<Apartment>(apartmentId);

                        var queryApartments = session.CreateQuery("from Apartment where Model = :model and Id <> :apartmentId")
                            .SetParameter("model", mainApartment.Model)
                            .SetParameter("apartmentId", mainApartment.Id); ;
                        var apartments = queryApartments.List<Apartment>();

                        var queryRooms = session.CreateQuery("from Room where Apartment_id = :apartmentId")
                            .SetParameter("apartmentId", mainApartment.Id);
                        var rooms = queryRooms.List<Room>();

                        Room newRoom;
                        foreach (var apartment in apartments)
                        {
                            foreach (var existingRoom in rooms)
                            {
                                newRoom = new Room()
                                {
                                    RoomGroup = existingRoom.RoomGroup,
                                    Mark = existingRoom.Mark,
                                    Type = existingRoom.Type,
                                    Name = existingRoom.Name,
                                    AreaValue = existingRoom.AreaValue
                                };
                                apartment.Rooms.Add(newRoom);
                            }

                            session.Update(apartment);
                        }

                        transaction.Commit();
                    }
                    catch (ADOException exception)
                    {
                        throw new Exception(exception.Message);
                    }
                }
            }
        }

        #endregion
    }
}
